﻿Imports System.Globalization

Public Class Money
    Implements IComparable

    Private _amount As Double
    Private _cur As Currency
    Public Sub New(amount As Double, Optional ByVal currency As Currency = Currency.EUR)
        _amount = amount
        _cur = currency
    End Sub

    Public Property Amount As Double
        Get
            Return _amount
        End Get
        Set(value As Double)
            _amount = value
        End Set
    End Property

    Public Property AmountString As String
        Get
            Return ToString()
        End Get
        Set(value As String)
            Dim t As String = value
            If t.Contains(GetCurrencySymbol) Then
                t.Replace(GetCurrencySymbol, "")
            End If
            t = t.Trim
            Amount = CDbl(t)
        End Set
    End Property

    Public Property Currency As Currency
        Get
            Return _cur
        End Get
        Set(value As Currency)
            _cur = value
        End Set
    End Property

    Public Function GetCurrencySymbol() As String
        Dim cur As String = ""
        Select Case Currency
            Case Currency.EUR
                cur = "€"
            Case Currency.CHF
                cur = "CHF"
            Case Currency.USD
                cur = "$"
        End Select
        Return cur
    End Function

    Public Overrides Function ToString() As String
        Dim nfi = DirectCast(CultureInfo.InvariantCulture.NumberFormat.Clone, NumberFormatInfo)
        nfi.NumberGroupSeparator = "."
        nfi.NumberDecimalSeparator = ","
        nfi.NumberDecimalDigits = 2
        Return Amount.ToString("n", nfi) + " " + GetCurrencySymbol()
    End Function

    Public Overrides Function Equals(obj As Object) As Boolean
        If TypeOf (obj) Is Money Then
            Dim arg As Money = obj
            If arg.Amount = Amount AndAlso arg.Currency = Currency Then
                Return True
            Else : Return False
            End If
        End If
        Try
            Dim d As Double = obj
            If Amount = d Then
                Return True
            Else : Return False
            End If
        Catch ex As Exception
            Return False
        End Try
    End Function

#Region "Operators"
    Public Shared Operator +(ByVal money1 As Money, ByVal money2 As Money) As Money
        If money1 IsNot Nothing AndAlso money2 IsNot Nothing Then
            If money1.Currency <> money2.Currency Then
                Throw New Exception("Unterschiedliche Währungen")
            End If
            Return New Money(money1.Amount + money2.Amount, money1.Currency)
        End If
        Return New Money(0)
    End Operator

    Public Shared Operator +(ByVal money1 As Money, ByVal amount2 As Double) As Money
        Return New Money(money1.Amount + amount2, money1.Currency)
    End Operator

    Public Shared Operator -(ByVal money1 As Money, ByVal money2 As Money) As Money
        If money1.Currency <> money2.Currency Then
            Throw New Exception("Unterschiedliche Währungen")
        End If
        Return New Money(money1.Amount - money2.Amount, money1.Currency)
    End Operator

    Public Shared Operator -(ByVal money1 As Money, ByVal amount2 As Double) As Money
        Return New Money(money1.Amount - amount2, money1.Currency)
    End Operator

    Public Shared Operator *(ByVal money1 As Money, ByVal money2 As Money) As Money
        If money1.Currency <> money2.Currency Then
            Throw New Exception("Unterschiedliche Währungen")
        End If
        Return New Money(money1.Amount * money2.Amount, money1.Currency)
    End Operator

    Public Shared Operator *(ByVal money1 As Money, ByVal amount2 As Double) As Money
        Return New Money(money1.Amount * amount2, money1.Currency)
    End Operator

    Public Shared Operator /(ByVal money1 As Money, ByVal money2 As Money) As Money
        If money1.Currency <> money2.Currency Then
            Throw New Exception("Unterschiedliche Währungen")
        End If
        Return New Money(money1.Amount / money2.Amount, money1.Currency)
    End Operator

    Public Shared Operator /(ByVal money1 As Money, ByVal amount2 As Double) As Money
        Return New Money(money1.Amount / amount2, money1.Currency)
    End Operator

    Public Shared Operator =(ByVal money1 As Money, ByVal money2 As Money) As Boolean
        If money1.Amount = money2.Amount AndAlso money1.Currency = money2.Currency Then
            Return True
        End If
        Return False
    End Operator

    Public Shared Operator <>(ByVal money1 As Money, ByVal money2 As Money) As Boolean
        Return Not money1 = money2
    End Operator

    Public Shared Operator <(ByVal money1 As Money, ByVal money2 As Money) As Boolean
        Return money1.Amount < money2.Amount
    End Operator

    Public Shared Operator <(ByVal money1 As Money, ByVal money2 As Double) As Boolean
        Return money1.Amount < money2
    End Operator

    Public Shared Operator >(ByVal money1 As Money, ByVal money2 As Money) As Boolean
        Return money1.Amount > money2.Amount
    End Operator

    Public Shared Operator >(ByVal money1 As Money, ByVal money2 As Double) As Boolean
        Return money1.Amount > money2
    End Operator
#End Region

    Public Function CompareTo(obj As Object) As Integer Implements System.IComparable.CompareTo
        Try
            Dim t As Money = obj
            Return Amount - t.Amount
        Catch ex As Exception
            Return 0
        End Try
    End Function
End Class

Public Class EMoney
    Inherits Money

    Public Sub New(amount As Double, Optional Gross As Boolean = True, Optional ByVal currency As Currency = Currency.EUR)
        MyBase.New(amount, currency)
        IsGross = Gross
    End Sub

    Public Property IsGross As Boolean
End Class

Public Enum Currency
    EUR = 0
    USD = 1
    CHF = 3
End Enum
